#ifndef _WIFI_H
#define _WIFI_H

#define EXAMPLE_ESP_WIFI_SSID      "ZClubCoffeeSettings"
#define EXAMPLE_ESP_WIFI_CHANNEL   0
#define EXAMPLE_MAX_STA_CONN       10

tcpip_adapter_ip_info_t localApIp;
tcpip_adapter_ip_info_t localStaIp;

typedef struct {
	wifi_sta_config_t sta;
	wifi_ap_config_t ap;
} custom_wifi_config_t;

typedef enum {
    WIFI_CONNECT_OK,
    WIFI_CONNECT_NOT_USE_NET,
    WIFI_CONNECT_NO_SSID,
	WIFI_CONNECT_CONFIG_FAIL,
    WIFI_CONNECT_CONNECT_FAIL,
	WIFI_CONNECT_WIFI_NOT_STARTED,
} wifiContentResult_t;

static custom_wifi_config_t wifiConfig = {
	.sta = {
		.ssid = "",
		.password = "",
		.bssid_set = false,
	},
	.ap = {
		.ssid = EXAMPLE_ESP_WIFI_SSID,
		.ssid_len = strlen(EXAMPLE_ESP_WIFI_SSID),
		.channel = EXAMPLE_ESP_WIFI_CHANNEL,
		.max_connection = EXAMPLE_MAX_STA_CONN,
		.authmode = WIFI_AUTH_OPEN
	},
};

wifiContentResult_t wifiConnect() {
	esp_err_t err;
	// 是否需要联网
	loadSettingByItem(ST_USE_NET);
	if(stGroup[ST_USE_NET].intValue == 0) {
		log("use net false");
		dispInitInfo("WiFi init done.");
		return WIFI_CONNECT_NOT_USE_NET;
	}
	else {
		loadSettingByItem(ST_SSID);
		if(strcmp(stGroup[ST_SSID].strValue, "") == 0) {
			log("no ssid");
			return WIFI_CONNECT_NO_SSID;
		}
		loadSettingByItem(ST_PASSWORD);
		log("connect to ssid = %s, password = %s", stGroup[ST_SSID].strValue, stGroup[ST_PASSWORD].strValue);
		memcpy(wifiConfig.sta.ssid, stGroup[ST_SSID].strValue, sizeof(wifiConfig.sta.ssid));
		memcpy(wifiConfig.sta.password, stGroup[ST_PASSWORD].strValue, sizeof(wifiConfig.sta.ssid));

		err = esp_wifi_set_config(ESP_IF_WIFI_STA, &wifiConfig.sta);
		if(err != ESP_OK) {
			return WIFI_CONNECT_CONFIG_FAIL;
		}
		LOG_ERR(esp_wifi_disconnect());
		err = esp_wifi_connect();
		// log("err = %d", err);
		if(err == ESP_ERR_WIFI_NOT_STARTED) {
			return WIFI_CONNECT_WIFI_NOT_STARTED;
		}
		else {
			return WIFI_CONNECT_OK;
		}
	}
}

static void wifiEventH(void* arg, esp_event_base_t eventBase, int32_t eventId, void* eventData) {
	if(eventBase == WIFI_EVENT) {
		if(eventId == WIFI_EVENT_AP_START) {
			wifi_event_ap_staconnected_t* event = (wifi_event_ap_staconnected_t*) eventData;
			esp_err_t res_ap_get;
			res_ap_get = tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_AP, &localApIp);
			if(res_ap_get == ESP_OK){
				sprintf(apIpStr, IPSTR, IP2STR(&localApIp.ip));
			}
			xEventGroupSetBits(eventGroup, EVENT_WIFI_AP_START);
			xEventGroupClearBits(eventGroup, EVENT_WIFI_AP_STOP);
		}
		else if(eventId == WIFI_EVENT_AP_STOP) {
			xEventGroupClearBits(eventGroup, EVENT_WIFI_AP_START);
			xEventGroupSetBits(eventGroup, EVENT_WIFI_AP_STOP);
		}
		else if(eventId == WIFI_EVENT_STA_CONNECTED) {
			xEventGroupSetBits(eventGroup, EVENT_WIFI_CONNECTED);
			xEventGroupClearBits(eventGroup, EVENT_WIFI_DISCONNECTED);			
		}
		else if(eventId == WIFI_EVENT_STA_DISCONNECTED) {
			xEventGroupClearBits(eventGroup, EVENT_WIFI_CONNECTED);
			xEventGroupSetBits(eventGroup, EVENT_WIFI_DISCONNECTED);
		}
	}
	else if(eventBase == IP_EVENT) {
		if(eventId == IP_EVENT_STA_GOT_IP) {
			ip_event_got_ip_t *event = (ip_event_got_ip_t *)eventData;
			sprintf(staIpStr, IPSTR, IP2STR(&event->ip_info.ip));
			xEventGroupSetBits(eventGroup, EVENT_WIFI_GOT_IP);
		}
	}
}



static bool wifiApInit() {
	// esp_netif_config_t netifConfig = ESP_NETIF_DEFAULT_WIFI_AP();
	// esp_netif_t *netif = esp_netif_new(&netifConfig);
	// assert(netif);
	// esp_netif_attach_wifi_ap(netif);
	esp_netif_create_default_wifi_ap();
	return true;
}

static bool wifiStaInit() {
	// esp_netif_config_t netifConfig = ESP_NETIF_DEFAULT_WIFI_STA();
	// esp_netif_t *netif = esp_netif_new(&netifConfig);
	// assert(netif);
	// esp_netif_attach_wifi_station(netif);
	esp_netif_create_default_wifi_sta();
	return true;
}

void wifiReConnect() {
	if(stGroup[ST_USE_NET].intValue) {
		log("reconnect wifi...");
		static int count = 3;
		wifiContentResult_t res;
		log("Wi-Fi disconnected, trying to reconnect...");
		if (count > 0) {
			res = wifiConnect();
			if (res == WIFI_CONNECT_WIFI_NOT_STARTED || res == WIFI_CONNECT_NOT_USE_NET) {
				return;
			}
			count--;
		} else {
			log("Try max connect count, but failed");
			if(pageCurrent(PAGE_INFO)) {
				pageShow(PAGE_HOME);
			}
		}
	}
	else {
		log("not use net");
	}
}

void wifiReConnectTask() {
	wifiReConnect();
	vTaskDelete(NULL);
}

void wifiInit() {
	
	LOG_ERR(esp_netif_init());
	
	LOG_ERR(esp_event_loop_create_default());
	wifiApInit();
	wifiStaInit();
	wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
	LOG_ERR(esp_wifi_init(&cfg));
	// ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_FLASH));

	LOG_ERR(initFs());
	LOG_ERR(startRestServer("/www"));
	dispInitInfo("Init WiFi...");


	LOG_ERR(esp_wifi_set_default_wifi_sta_handlers());

	LOG_ERR(esp_wifi_start());
	LOG_ERR(esp_wifi_set_ps(WIFI_PS_NONE));
	LOG_ERR(esp_wifi_set_mode(WIFI_MODE_APSTA));
	// ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
	LOG_ERR(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &wifiEventH, NULL));
	LOG_ERR(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &wifiEventH, NULL));

	esp_wifi_set_config(ESP_IF_WIFI_AP, &wifiConfig.ap);

	wifiConnect();
	dispInitInfo("WiFi init done.");
}

void wifiInitTask() {
	wifiInit();
	vTaskDelete(NULL);
}


#endif